package org.jeecg.modules.charge.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.util.AliyunOssHelper;
import org.jeecg.common.util.ComUtil;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.StringUtils;
import org.jeecg.entity.charge.ChargeBills;
import org.jeecg.entity.charge.ChargeInvoice;
import org.jeecg.entity.charge.ChargeInvoiceInfo;
import org.jeecg.entity.charge.ChargeInvoiceRequest;
import org.jeecg.enums.InvoiceTypeEnum;
import org.jeecg.modules.charge.entity.BwInvoiceEntity.*;
import org.jeecg.modules.charge.entity.*;
import org.jeecg.modules.charge.entity.YyInvoiceEntity.InvoiceOfflineConfig;
import org.jeecg.modules.charge.mapper.ComConfigMapper;
import org.jeecg.modules.charge.service.IChargeInvoiceInfoService;
import org.jeecg.modules.charge.service.IChargeInvoiceService;
import org.jeecg.modules.charge.service.impl.BlueInvoiceService;
import org.jeecg.modules.charge.service.impl.ChargeEleinvoiceServiceImpl;
import org.jeecg.modules.charge.service.impl.ChargeInvoiceRequestServiceImpl;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.service.impl.SysDepartServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 作者Houms:
 * @version 创建时间：2020年01月08日 下午2:11:43 用友发票开具接口
 */
@Slf4j
@Api(tags="用友开票接口")
@RestController
@RequestMapping(value = "/b/charge/makeInvoiceYy")
public class CharegeYyInvoiceController {
	/** SLF4J日志 */
	protected static final Logger logger = LoggerFactory.getLogger(CharegeYyInvoiceController.class);
	@Value("${yy.url}")
	private String bwinvoiceUrl;
	@Value("${lvcert.url}")
	private String certUrl;
	@Value("${backblue.url}")
	private String backUrl;
	@Autowired
	private ChargeEleinvoiceServiceImpl eleInvoiceService;
	@Autowired
	private ChargeInvoiceRequestServiceImpl invoiceReqService;
	@Autowired
	private BlueInvoiceService blueInvoiceService;
	@Autowired
	private SysDepartServiceImpl sysDepartServiceImpl;
	@Autowired
	private IChargeInvoiceInfoService invoiceInfoService;
	@Autowired
	private IChargeInvoiceService invoiceService;
	@Autowired
	private ComConfigMapper comConfigMapper;

	@AutoLog(value = "用友开具蓝票接口")
	@ApiOperation(value="用友开具蓝票接口", notes="用友开具蓝票接口")
	@PostMapping(value = "openblue")
	@ResponseBody
	public Result<Integer> openBlue(@RequestBody String req,HttpServletRequest request, HttpServletResponse response) throws Exception {
		StringBuffer sb = new StringBuffer("");
		String url = bwinvoiceUrl;
		Date startDate = new Date();// 初始化开始时间
		SimpleDateFormat smf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		//转化对应开票格式化日期
		SimpleDateFormat kpsmf = new SimpleDateFormat("yyyyMMddHHmmss");
		String now = smf.format(startDate);
		// InvoiceReqDeail 作为请求开票时插入到数据库中的对象 BlueInvoice 作为开票的对象去请求开票
		// BlueInvoiceDetailed作为开票的下级详情
		ChargeInvoiceRequest invoiceReqDeail = JSONObject.parseObject(req, ChargeInvoiceRequest.class);
		// ChargeBillsOrder
		// order=elecInvoiceService.getOrder(invoiceReqDeail.getOrderNum());
		request.setAttribute("tenantId", invoiceReqDeail.getTenantId());
		if (null != invoiceReqDeail.getOrderNum() && StringUtils.isNotEmpty(invoiceReqDeail.getOrderNum())) {
			String isExit = invoiceReqService.selectByOrderNum(invoiceReqDeail.getOrderNum());
			if (null != isExit && StringUtils.isNotEmpty(isExit)) {
				logger.info("订单号已存在");
				return Result.error("订单号已存在");
			}
		}
		invoiceReqDeail.setId(String.valueOf(IdWorker.getId()));
		invoiceReqDeail.setDelFlag("0");
		if (null == invoiceReqDeail.getRoomId() || StringUtils.isEmpty(invoiceReqDeail.getRoomId())) {
			logger.info("房间ID为空");
			return Result.error("房间ID为空");
		}
		BlueInvoice bi=new BlueInvoice();
		String fpqqlsh = StringUtils.getRandomStringByLength(4) + DateUtils.detailStr(new Date());
		invoiceReqDeail.setFpqqlsh(fpqqlsh);
		invoiceReqDeail.setInvoiceStatus("1");//默认为开票中
		bi.setFpqqlsh(fpqqlsh);
		bi.setJshj(invoiceReqDeail.getMoney());
		// 房间对应部门的id
		String projectId = invoiceReqService.getOidByRid(invoiceReqDeail.getRoomId(), "2");
		String zhid=invoiceReqService.getOidByRid(invoiceReqDeail.getRoomId(),"3");
		String oid = invoiceReqService.getOidByRid(invoiceReqDeail.getRoomId(), "1");
		// 获取公司ID
		SysDepart o = sysDepartServiceImpl.getCompanyByDepartId(oid);
		// 获取公司ID
		InvoiceOfflineConfig config = comConfigMapper.getYyConfig(projectId);
		if (null == config) {
			logger.info("项目暂无对应的配置");
			return Result.error("项目暂无对应的配置");
		}
		String adress="";
		List<String> roomIds=null;//用于存放多个房间ID
		if(null==invoiceReqDeail.getFiled4() || StringUtils.isEmpty(invoiceReqDeail.getFiled4())) {
			adress=invoiceReqService.getOidByRid(invoiceReqDeail.getRoomId(), "5");
//			invoiceReqDeail.setPayMethod("APP");  TODO
			invoiceReqDeail.setInvoiceStatus("2");
			invoiceReqDeail.setRemarks("APP请求支付,开票中!");
		}
		invoiceReqDeail.setCustomerId(zhid);
		invoiceReqDeail.setProjectId(projectId);
		String tel="";
		String address="";
		if(null!=invoiceReqDeail.getTel() && StringUtils.isNotEmpty(invoiceReqDeail.getTel())) {
			bi.setTel(invoiceReqDeail.getTel());
			tel=invoiceReqDeail.getTel();
		}
		if(null!=invoiceReqDeail.getEin() && StringUtils.isNotEmpty(invoiceReqDeail.getEin())) {
			bi.setGmf_nsrsbh(invoiceReqDeail.getEin());
		}
		if(null!=invoiceReqDeail.getEmail() && StringUtils.isNotEmpty(invoiceReqDeail.getEmail())) {
			bi.setE_mails(invoiceReqDeail.getEmail());
		}
		if(null!=invoiceReqDeail.getAccount() && StringUtils.isNotEmpty(invoiceReqDeail.getAccount())) {
			bi.setGmf_yhzh(invoiceReqDeail.getAccount());
		}
		if(null!=invoiceReqDeail.getAddress() && StringUtils.isNotEmpty(invoiceReqDeail.getAddress())) {
			address=invoiceReqDeail.getAddress();
		}
		bi.setGmf_dzdh(address+" "+tel);
		bi.setGmf_mc(invoiceReqDeail.getGmfMc());
		bi.setComid(o.getId());
		bi.setAppid(config.getAppid());
		bi.setPassword(config.getPassword());
		bi.setXsf_nsrsbh(config.getXsfNsrsbh());
		bi.setXsf_dzdh(config.getXsfDzdh());
		bi.setXsf_mc(config.getXsfMc());
		bi.setXsf_yhzh(config.getXsfYhzh());
		bi.setCert_url(certUrl);
		bi.setOrgcode(config.getOrgcode());
		String blueUrl = url.trim()+config.getAppid();
		bi.setUrl(blueUrl);
		invoiceReqDeail.setReqUrl(blueUrl);
//拼接开票地址
		String billids = (String)invoiceReqDeail.getBillIds();
		if(null==billids || StringUtils.isEmpty(billids)) {
			logger.info("账单ID为空");
			return Result.error("账单ID为空");
		}
		List<String> bids=new ArrayList<String>();
		//如果是日常收费，会有对应的账单ID
		String str[] = billids.split(",");
		for(int i=0;i<str.length;i++) {
			bids.add(str[i]);
		}
		if(null==bids || bids.size()==0) {
			logger.info("新拼接账单为空");
			return Result.error("新拼接账单为空");
		}
		String bz="";
		List<BlueInvoiceDetailed> details=new ArrayList<BlueInvoiceDetailed>();
		List<ChargeBills> bills= null; //invoiceReqService.getBillsByids(bids);
		for(int i=0;i<bills.size();i++) {
			bz=bills.get(0).getZjCny()+"至"+bills.get(bills.size()-1).getZjCny();
		}
		if(null!=adress && StringUtils.isNotEmpty(adress)) {
			bz=bz+"\n"+adress;
		}
		bi.setBz(bz);
		List<ChargeBills> newbills=new ArrayList<ChargeBills>();
		if(null!=bills && bills.size()>0) {
			for (ChargeBills bill : bills) {
				boolean flag = false;
				//用于存放对应的摘要
				List<String> zys = new ArrayList<String>();
				String cny = bill.getZjCny();
				//循环遍历查询相同的收费项目下，相同的金额下拼接成请求详细参数
				for (ChargeBills b : newbills) {
					if (bill.getFeeitemId().equals(b.getFeeitemId()) && bill.getDue().compareTo(b.getDue()) ==0) {
						zys.add(b.getZjCny());
						cny += "," + b.getZjCny();
						b.setNum(b.getNum() + 1);
						b.setZjCny(cny);
						flag = true;
					}
				}
				if (!flag) {
					newbills.add(bill);
				}
			}
			for (ChargeBills b : newbills) {
				if (null != b.getZjCny() || StringUtils.isEmpty(b.getZjCny())) {
					String cnys[] = b.getZjCny().split(",");
					String newcnys[] = StringUtils.buffSort(cnys);
					b.setZjCny(newcnys[0] + ">" + newcnys[newcnys.length - 1]);

				}
				BlueInvoiceDetailed detail = new BlueInvoiceDetailed();
				Double jesum = new BigDecimal(b.getNum()).multiply(b.getDue()).doubleValue();
				detail.setXmsl(b.getNum());
				detail.setFeeCode(b.getFeeitemId());
				detail.setSl(b.getTaxRate() / 100);
				//临时存放商品编码
				detail.setSpbm(b.getMaintenanceCost());
				detail.setSubjectCode(b.getFeeitemId());
				detail.setUnitprice(b.getDue().setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
				detail.setXmjshj(new BigDecimal(jesum).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
				detail.setXmmc(b.getFeeName());
				detail.setZy(b.getZjCny());
				details.add(detail);
			}
			bi.setBuildUrl(backUrl);
			//获取凭证配置
			VoucherProject voucher = comConfigMapper.getVoucherConfig(projectId,invoiceReqDeail.getRoomId());
			if(null != voucher){
				invoiceReqDeail.setVoucherItem(voucher.getVoucherItem());
				invoiceReqDeail.setVoucherCompany(voucher.getComName());
			}
		}
		bi.setDetails(details);
		JSONObject json=new JSONObject();
		json.put("bi", bi);
		invoiceReqDeail.setReq(json.toJSONString());
		// 判断是否需要封账
		if (null != config.getFiled2() && StringUtils.isNotEmpty(config.getFiled2())) {
			Integer sealDate = Integer.valueOf(config.getFiled2());
			// 将开票状态改为5，表示封账待开的账单，在次月1号轮训开具。不进行请求
			Integer dd = DateUtils.getDayByDate(now);
			if (dd > sealDate) {
				String newdate = DateUtils.getFirstDay(now);
				invoiceReqDeail.setInvoiceStatus("0");
				invoiceReqDeail.setRemarks("封账待开!");
				invoiceReqDeail.setMakeInvoiceDate(smf.parse(newdate));
				// 封账日
				eleInvoiceService.insertInvoiceReq(invoiceReqDeail);
				return Result.ok("封账待开");
			}
		}
		//开票信息插入记录表
		Integer reqresult=eleInvoiceService.insertInvoiceReq(invoiceReqDeail);
		try{
			if(reqresult > 0){
				for(BlueInvoiceDetailed detail:details) {
					BigDecimal big = new BigDecimal(detail.getXmjshj()/(1+detail.getSl()));
					Double income=big.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
					Double tax=detail.getXmjshj()-income;
					detail.setIncome(income);
					detail.setTax(tax);
					detail.setInvoiceRequestId(invoiceReqDeail.getId());
					detail.setId(String.valueOf(IdWorker.getId()));
					invoiceReqService.addRequestInfo(detail);
				}
			}
		}catch (Exception e){
			log.error(e.getMessage(), e);
			logger.info("电票详情插入异常！");
			return Result.error("电票详情插入异常！");
		}

		String result=null;
		try {
			result=blueInvoiceService.callInvoiceApply(bi);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			logger.info("未知错误");
			return Result.error("未知错误");
		}
		JSONObject jsStr = JSONObject.parseObject(result);
		String code=jsStr.get("code").toString().trim();
		//返回具体信息
		String msg=jsStr.get("msg").toString().trim();
		//如果是0000则成功
		if("0000".equals(code)) {
			return Result.ok("开票成功!");
		}else {
			String remarks=code+","+msg;
			if(bi != null && StringUtils.isNotEmpty(bi.getFpqqlsh())){
				eleInvoiceService.updateInvoiceReq("3",bi.getUrl(),remarks,bi.getFpqqlsh());
			}
			return Result.ok("开票失败!");
		}
	}
	static class CallbackParam implements Serializable {
		private static final long serialVersionUID = 1L;
		public CallbackParam() {
		}

		public String data;
		public String code;
		public String msg;
		public String fpqqlsh;
		public String pdf;
		public String shareurl;
		public String sharecode ;
		@Override
		public String toString() {
			StringBuffer sb = new StringBuffer();
			sb.append("\r\ndata=");
			sb.append(data);
			sb.append("\r\ncode=");
			sb.append(code);
			sb.append("\r\nmsg=");
			sb.append(msg);
			sb.append("\r\nfpqqlsh=");
			sb.append(fpqqlsh);
			sb.append("\r\npdf=");
			if (pdf != null && pdf.length() > 10) {
				sb.append(pdf.substring(0, 10));
				sb.append("....");
			} else {
				sb.append(pdf);
			}
			sb.append("\r\nshareurl=");
			sb.append(shareurl);
			sb.append("\r\nsharecode=");
			sb.append(sharecode);

			return sb.toString();
		}
	}

	@RequestMapping({ "callbackblue" })
	public String getResult(@RequestBody CallbackParam callbackParam,HttpServletResponse response,HttpServletRequest request) throws Exception {
		log.info(callbackParam.toString());
		SimpleDateFormat sd=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String fpqqlsh = callbackParam.fpqqlsh;
		String pdf = callbackParam.pdf;
		String data = callbackParam.data;
		ChargeInvoiceRequest detail=invoiceReqService.getDetailByLsh(fpqqlsh);
		if(null==detail) {
			log.info("暂无发票请求!");
			return null;
		}
		request.setAttribute("tenantId",detail.getTenantId());
		invoiceReqService.updateResByfplsh(fpqqlsh, callbackParam.toString());
		String pdfurl=null;
		//将PDF的流转为流传到阿里云数据库中
		if(StringUtils.isNotEmpty(pdf)) {
			//上传到oss获取url
			byte[] stringImage =blueInvoiceService.getStringImage(pdf);
			InputStream sbs = new ByteArrayInputStream(stringImage);
			String key = "pic/";
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			String ymd = sdf.format(new Date());
			// 新的图片名称(真实名称)
			String newFileName = UUID.randomUUID() + ".pdf";
			// 新图片的路径
			key += ymd + "/" + newFileName;
			Boolean pic_flg = AliyunOssHelper.put(key, sbs);
			if (pic_flg) {
				pdfurl = AliyunOssHelper.getUrlPath(key);
				/*resultinfo.put("pdfurl", pdfurl);*/
				log.info(pdfurl);
			} else {
				log.info("上传失败");
			}
		}
		//从data中解析出发票代码和发票号码并更新
		Map<String,Object> maps = (Map) JSONObject.parse(data);
		String fpdm = (String)maps.get("fpDm");
		String fphm = (String)maps.get("fpHm");
		String kpr	= (String)maps.get("kpr");
		String skr  = (String)maps.get("skr");
		BigDecimal hjse=(BigDecimal)maps.get("hjse");
		BigDecimal hjje=(BigDecimal)maps.get("hjje");
		String kprq=(String)maps.get("kprq");
		String newInvoiceDate=ComUtil.dateTimeFmt("" + kprq, "yyyy-MM-dd HH:mm:ss");
		detail.setFpdm(fpdm);
		detail.setFphm(fphm);
        detail.setFiled6(kpr);
		//插入票据和票据信息表中
		ChargeInvoice invoice=new ChargeInvoice();
		invoice.setId(String.valueOf(IdWorker.getId()));
		invoice.setProjectId(detail.getProjectId());
		if(null!=detail.getFiled7() && StringUtils.isNotEmpty(detail.getFiled7())) {
			invoice.setRemarks(detail.getFiled7());
		}
		invoice.setInvoiceHm(fphm);
		invoice.setInvoiceDm(fpdm);
		//更新对应的开票日期
		invoice.setMakeInvoiceDate(ComUtil.parseDate(newInvoiceDate));
		invoice.setPayer(detail.getGmfMc());
		invoice.setMoney(detail.getMoney());
		//更新对应的收款日期
		invoice.setZjSkrq(detail.getMakeInvoiceDate());
		invoice.setPayMethod(detail.getPayMethod());
		invoice.setInvoiceMan(kpr);
		invoice.setPayee(skr);
		invoice.setPayMethod(detail.getPayMethod());
		invoice.setAddress(detail.getAddress());
		invoice.setCustomerId(detail.getCustomerId());
		invoice.setPdfUrl(pdfurl);
		invoice.setCreateBy(detail.getCreateBy());
		invoice.setUpdateBy(detail.getUpdateBy());
		invoice.setDelFlag("0");
		//表示电子发票
		invoice.setTicket(InvoiceTypeEnum.INVOICE_TYPE_ELE.getCode());
		String  pjid;
		//插入前查询此发票号码和代码是否存在，存在不给继续插入
		String fpcount=invoiceService.getIdByInvoice(fphm,fpdm);
		if(null==fpcount) {
			boolean re=invoiceService.save(invoice);
			//插入成功
			if(re) {
				pjid=invoice.getId();
				log.info("票据ID为:"+pjid);
				String evdetail=JSONObject.parseObject(JSONObject.parseObject(detail.getReq().toString()).getString("bi")).getString("details").toString();
				List<BlueInvoiceDetailed> tails=JSONObject.parseArray(evdetail, BlueInvoiceDetailed.class);
				List<ChargeInvoiceInfo> infos=new ArrayList<ChargeInvoiceInfo>();
				if(null!=tails && tails.size()>0) {
					//插入票据详情
					for(BlueInvoiceDetailed ta:tails) {
						ChargeInvoiceInfo info=new ChargeInvoiceInfo();
						info.setId(String.valueOf(IdWorker.getId()));
						info.setInvoiceId(pjid);
						info.setInvoiceDm(fpdm);
						info.setInvoiceHm(fphm);
						info.setAbstractInfo(ta.getZy());
						info.setAddress(detail.getAddress());
						info.setInvoiceObject(ta.getXmmc());
						info.setNum(ta.getXmsl());
						info.setUnitPrice(ta.getUnitprice());
						info.setMoney(ta.getXmjshj());
						info.setSubjectCode(ta.getSubjectCode());
						//todo 发票暂时未做
						//info.setFeeitemCode(ta.getFeeCode());
						info.setRate(ta.getSl());
						Double oldse=(ta.getXmjshj()/(1+ta.getSl()))*ta.getSl();
						Double se= new BigDecimal(oldse).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
						Double oldsr=ta.getXmjshj()-se;
						Double sr=new BigDecimal(oldsr).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
						info.setTax(se);
						info.setRealMoney(sr);
						info.setCreateBy(detail.getCreateBy());
						info.setUpdateBy(detail.getUpdateBy());
						infos.add(info);
					}
					invoiceInfoService.insertInfos(infos);
				}
			}else {

				log.info("发票请求为空!");
				return null;
			}
		}
		//重复票据
		else {
			detail.setInvoiceStatus("3");
			detail.setRemarks("轮训查询,票据已经插入!");
			invoiceReqService.updateById(detail);
			return null;
		}
		List<String> bids=new ArrayList<String>();
		String billids=detail.getBillIds().toString();
		//如果是日常收费，会有对应的账单ID
		if(null!=billids && StringUtils.isNotEmpty(billids)) {
			String str[] = billids.split(",");
			for(int i=0;i<str.length;i++) {
				bids.add(str[i]);
			}
		}
		//账单ID不为空，修改账单里的发票信息
		if(null!=bids && bids.size()>0) {
			log.info("开始修改账单中票据信息!");
			ChargeBills u=new ChargeBills();
			u.setInvoiceNo(fphm);
			u.setInvoiceGrnno(fpdm);
			u.setDateRange(pdfurl);
			u.setPayType(detail.getPayMethod());
			u.setZjSkrq(detail.getMakeInvoiceDate());
			u.setPayuserName(skr);
			u.setUpdateTime(new Date());
			u.setMakeinvoiceDate(ComUtil.parseDate(newInvoiceDate));
			u.setBillIds(bids);
			eleInvoiceService.updateBillsInvoice(u);
		}
        detail.setPdfUrl(pdfurl);
		detail.setInvoiceStatus("1");
		detail.setFpdm(fpdm);
		detail.setFphm(fphm);
		detail.setHjje(hjje.doubleValue());
		detail.setHjse(hjse.doubleValue());
		detail.setKprq(kprq);
		detail.setMakeInvoiceDate(ComUtil.parseDate(newInvoiceDate));
		detail.setRemarks("开票成功!");
		invoiceReqService.updateById(detail);
		JSONObject json=new JSONObject();
		json.put("code", "0000");
		json.put("msg", "success");
		log.info(json.toJSONString());
		response.getWriter().write(json.toJSONString());
		return null;
	}

}
